package org.KeyCrafter.server;

import io.netty.handler.codec.redis.RedisMessage;
import org.KeyCrafter.cmd.DBCommand;
import org.KeyCrafter.ds.dict.Dict;
import org.KeyCrafter.obj.KeyCrafterObject;
import org.KeyCrafter.server.session.ClientSession;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import static org.KeyCrafter.server.ServerConstants.KeyCrafter_ERR;
import static org.KeyCrafter.server.ServerConstants.KeyCrafter_OK;

public abstract class KVDB implements DBCommand {
    private static final String DEFAULT_DB_CLASS = "org.KeyCrafter.server.DefaultKVDB";
    protected static final ServerContext sc = ServerContext.DEFAULT;
    // 数据库id
    public abstract int id();
    // 键空间
    abstract Dict getKeySpace();
    // 过期键
    abstract Dict getExpires();
    // 平均 TTL
    public abstract long getAvgTTL();
    abstract void setAvgTTL(long avgTTL);
    // 键的过期时间
    public abstract long getExpire(String key);
    public abstract void setKey(String key, KeyCrafterObject val);
    public abstract KeyCrafterObject lookupKeyWrite(String key);
    public abstract KeyCrafterObject lookupKeyRead(String key);
    public abstract KeyCrafterObject lookupKeyReadOrReply(ClientSession c, String key, RedisMessage reply);
    public abstract void dbAdd(String key, KeyCrafterObject val);
    public abstract boolean delete(String key);
    public abstract void setExpire(String key, long when);
    // dirty 自增
    public abstract void incrDirty();
    public abstract void addDirty(int delta);

    // 切换数据库
    public static int selectDb(ClientSession c, int id) {
        // 确保 id 在正确范围内
        if (id < 0 || id >= sc.dbNum())
            return KeyCrafter_ERR;
        // 切换数据库
        c.setCurDB(sc.db(id));
        return KeyCrafter_OK;
    }

    public static KVDB newDefaultDb(int id) {
        try {
            Class<?> aClass = Class.forName(DEFAULT_DB_CLASS);
            Constructor<?> constructor = aClass.getDeclaredConstructor(int.class);
            return (KVDB) constructor.newInstance(id);
        } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
}
